<template>
  <doc-alert title="上传下载" url="https://doc.iocoder.cn/file/" />
  <el-row :gutter="10">
    <!-- 左侧文件夹树 -->
    <el-col :span="4" :xs="24">
      <ContentWrap class="h-1/1 !mb-0px">
        <DirTree @node-click="handleDirNodeClick" />
      </ContentWrap>
    </el-col>
    <el-col :span="20" :xs="24">
      <!-- 搜索 -->
      <ContentWrap>
        <el-form
          class="-mb-15px"
          :model="queryParams"
          ref="queryFormRef"
          :inline="true"
          label-width="68px"
        >
          <el-form-item label="文件路径" prop="path">
            <el-input
              v-model="queryParams.path"
              placeholder="请输入文件路径"
              clearable
              @keyup.enter="handleQuery"
            />
          </el-form-item>
          <!-- <el-form-item label="文件类型" prop="type" width="80">
            <el-input
              v-model="queryParams.type"
              placeholder="请输入文件类型"
              clearable
              @keyup.enter="handleQuery"
            />
          </el-form-item> -->

          <el-form-item label="创建时间" prop="createTime">
            <el-date-picker
              v-model="queryParams.createTime"
              value-format="YYYY-MM-DD HH:mm:ss"
              type="daterange"
              start-placeholder="开始日期"
              end-placeholder="结束日期"
              :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
            />
          </el-form-item>
          <el-form-item label="展示方式" width="80">
            <el-radio-group v-model="showType">
              <el-radio-button label="平铺" :value="1"> <Icon icon="ep:grid" /> </el-radio-button>
              <el-radio-button label="列表" :value="0">
                <Icon icon="zondicons:list" />
              </el-radio-button>
            </el-radio-group>
          </el-form-item>
          <el-form-item>
            <el-button @click="handleQuery"
              ><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button
            >
            <el-button @click="resetQuery"
              ><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button
            >
            <el-button type="primary" plain @click="openForm">
              <Icon icon="ep:upload" class="mr-5px" /> 上传文件
            </el-button>
            <el-button type="primary" v-if="checkedFiles.length > 0" plain @click="openMoveForm">
              更换分类
            </el-button>
            <el-button
              type="primary"
              v-if="checkedFiles.length > 0 && props.type == 'component'"
              @click="handleUse"
            >
              选择文件
            </el-button>
          </el-form-item>
        </el-form>
      </ContentWrap>

      <!-- 列表 -->
      <ContentWrap class="!mb-0px">
        <el-tabs v-model="queryParams.fileType" @tab-click="handleClick">
          <el-tab-pane
            v-for="item in getIntDictOptions(DICT_TYPE.MATERIAL_FILE_TYPE)"
            :key="item.value"
            :name="item.value"
          >
            <template #label>
              <span>{{ `${item.label}` }}</span>
            </template>
          </el-tab-pane>
        </el-tabs>
        <el-table v-loading="loading" :data="list" v-if="showType == 0">
          <!-- 1. 多选模式（不能使用type="selection"，Element会忽略Header插槽） -->
          <el-table-column width="55">
            <template #header>
              <el-checkbox
                v-model="isCheckAll"
                :indeterminate="isIndeterminate"
                @change="handleCheckAll"
              />
            </template>
            <template #default="{ row }">
              <el-checkbox
                v-model="checkedStatus[row.id]"
                @change="(checked: boolean) => handleCheckOne(checked, row, true)"
              />
            </template>
          </el-table-column>
          <el-table-column
            label="文件名"
            align="center"
            prop="name"
            :show-overflow-tooltip="true"
          />
          <el-table-column
            label="文件路径"
            align="center"
            prop="path"
            :show-overflow-tooltip="true"
          />
          <el-table-column label="URL" align="center" prop="url" :show-overflow-tooltip="true" />
          <el-table-column
            label="文件大小"
            align="center"
            prop="size"
            width="120"
            :formatter="fileSizeFormatter"
          />
          <el-table-column label="文件类型" align="center" prop="type" width="180px" />
          <el-table-column label="文件内容" align="center" prop="url" width="110px">
            <template #default="{ row }">
              <el-image
                v-if="row.type.includes('image')"
                class="h-40px w-40px rounded-4px"
                lazy
                :src="row.url"
                :preview-src-list="[row.url]"
                preview-teleported
                fit="contain"
              />

              <WxVideoPlayer
                v-else-if="row.type.includes('video')"
                class="h-40px w-40px rounded-4px"
                :url="row.url"
              />
              <WxVoicePlayer
                class="h-40px w-40px rounded-4px"
                v-else-if="row.type.includes('audio')"
                :url="row.url"
              />
              <el-link
                v-else-if="row.type.includes('pdf')"
                type="primary"
                :href="row.url"
                :underline="false"
                target="_blank"
                >预览</el-link
              >
              <el-link
                v-else
                type="primary"
                download
                :href="row.url"
                :underline="false"
                target="_blank"
                >下载</el-link
              >
            </template>
          </el-table-column>
          <el-table-column
            label="上传时间"
            align="center"
            prop="createTime"
            width="180"
            :formatter="dateFormatter"
          />
          <el-table-column label="操作" align="center">
            <template #default="scope">
              <el-button
                link
                type="danger"
                @click="handleDelete(scope.row.id)"
                v-hasPermi="['infra:file:delete']"
              >
                删除
              </el-button>
            </template>
          </el-table-column>
          <template #empty>
            <Empty />
          </template>
        </el-table>
        <!-- 大图列表 -->

        <el-row v-loading="loading" v-if="showType == 1" :gutter="10">
          <template v-if="list.length > 0">
            <el-col :xl="3" :lg="4" :md="4" :sm="12" :xs="12" v-for="item in list" :key="item.id">
              <div class="waterfall-item">
                <div class="p-10px">
                  <el-image
                    v-if="item.type.includes('image')"
                    class="h-130px w-100%"
                    lazy
                    :src="item.url"
                    :preview-src-list="[item.url]"
                    preview-teleported
                    fit="contain"
                  />

                  <WxVideoPlayer
                    class="h-130px w-100% text-center flex items-center justify-center m-b-4px"
                    v-else-if="item.type.includes('video')"
                    :url="item.url"
                  />
                  <WxVoicePlayer
                    class="h-130px! w-100%! text-center flex items-center justify-center m-b-4px"
                    v-else-if="item.type.includes('audio')"
                    :url="item.url"
                  />

                  <div
                    v-else
                    class="h-130px w-100% text-center flex flex-col items-center justify-center m-b-4px"
                  >
                    <Icon icon="ant-design:container-filled" :size="80" />

                    <el-link
                      v-if="item.type.includes('pdf')"
                      type="primary"
                      :href="item.url"
                      :underline="false"
                      target="_blank"
                      >预览</el-link
                    >
                    <el-link
                      v-else
                      type="primary"
                      :href="item.url"
                      :underline="false"
                      target="_blank"
                    >
                      <el-text truncated> {{ item.name }}</el-text
                      >下载</el-link
                    >
                  </div>
                </div>
                <div
                  class="border-t-solid border-t-1 p-x-10px"
                  style="border-color: var(--el-border-color)"
                >
                  <el-tooltip :content="item.name" placement="top">
                    <el-text truncated>
                      <el-checkbox
                        v-model="checkedStatus[item.id]"
                        @change="(checked: boolean) => handleCheckOne(checked, item, true)"
                      />
                      {{ item.name }}</el-text
                    >
                  </el-tooltip>
                </div>
                <el-row justify="center">
                  <el-button
                    link
                    type="danger"
                    @click="handleDelete(item.id)"
                    v-hasPermi="['infra:file:delete']"
                  >
                    删除
                  </el-button>
                </el-row>
              </div>
            </el-col>
          </template>

          <div v-else class="flex justify-center w-full">
            <Empty />
          </div>
        </el-row>
        <!-- 分页 -->
        <Pagination
          :total="total"
          v-model:page="queryParams.pageNo"
          v-model:limit="queryParams.pageSize"
          :page-sizes="pageSizes"
          @pagination="getList"
        />
      </ContentWrap>
    </el-col>
  </el-row>

  <!-- 表单弹窗：添加/修改 -->
  <FileForm ref="formRef" @success="getList" />
  <!-- 文件更换分类 -->
  <MoveForm ref="moveformRef" @success="getList" />
</template>
<script lang="ts" setup>
import { fileSizeFormatter } from '@/utils'
import { dateFormatter } from '@/utils/formatTime'
import * as FileApi from '@/api/infra/file'
import FileForm from './FileForm.vue'
import { onMounted } from 'vue'
import DirTree from './DirTree.vue'
import MoveForm from './MoveForm.vue'
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'

import WxVideoPlayer from '@/views/mp/components/wx-video-play'
import WxVoicePlayer from '@/views/mp/components/wx-voice-play'

type File = {
  id: number
  url: string
}

defineOptions({ name: 'InfraFile' })
const props = defineProps({
  type: {
    default: 'page',
    type: String
  }
})
const emit = defineEmits(['selectFile'])
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化

const loading = ref(true) // 列表的加载中
const total = ref(0) // 列表的总页数
const list = ref([] as any) // 列表的数据
const queryParams = reactive({
  pageNo: 1,
  pageSize: 24,
  name: undefined,
  type: undefined,
  path: undefined,
  createTime: [] as any,
  typeId: undefined, //目录id
  fileType: 1
})
const showType = ref(1)
const queryFormRef = ref() // 搜索的表单

const pageSizes = ref([8, 16, 24, 48])
watch(
  () => showType.value,
  () => {
    if (showType.value == 1) {
      queryParams.pageSize = 24
      pageSizes.value = [8, 16, 24, 48]
    }
    if (showType.value == 0) {
      queryParams.pageSize = 10
      pageSizes.value = [10, 20, 30, 50, 100]
    }
  }
)

/** 初始化 **/
onMounted(() => {
  getList()
})
/** 查询列表 */
const getList = async () => {
  loading.value = true
  console.log(queryParams)
  try {
    const data = await FileApi.getFilePage(queryParams)
    list.value = data.list
    total.value = data.total
  } finally {
    loading.value = false
  }
}

/** 搜索按钮操作 */
const handleQuery = () => {
  queryParams.pageNo = 1
  getList()
}
const handleClick = () => {
  nextTick(() => {
    handleQuery()
  })
}
/** 重置按钮操作 */
const resetQuery = () => {
  queryFormRef.value.resetFields()
  handleQuery()
}

/** 添加/修改操作 */
const formRef = ref()
const openForm = () => {
  formRef.value.open()
}
/** 文件目录修改操作 */
const moveformRef = ref()
const openMoveForm = () => {
  moveformRef.value.open(checkedFiles.value)
}

/** 删除按钮操作 */
const handleDelete = async (id: number) => {
  try {
    // 删除的二次确认
    await message.delConfirm()
    // 发起删除
    await FileApi.deleteFile(id)
    message.success(t('common.delSuccess'))
    // 刷新列表
    await getList()
  } catch {}
}
/** 处理目录被点击 */
const handleDirNodeClick = async (row) => {
  queryParams.typeId = row.typeId
  await getList()
}
// 是否全选
const isCheckAll = ref(false)
// 全选框是否处于中间状态：不是全部选中 && 任意一个选中
const isIndeterminate = ref(false)
// 选中的素材
const checkedFiles = ref<File[]>([])
// 选中状态：key为素材ID，value为是否选中
const checkedStatus = ref<Record<string, boolean>>({})

/** 全选/全不选 */
const handleCheckAll = (checked: boolean) => {
  isCheckAll.value = checked
  isIndeterminate.value = false

  list.value.forEach((file) => handleCheckOne(checked, file, false))
}
// 查找素材在已选中素材列表中的索引
const findCheckedIndex = (file: File) => checkedFiles.value.findIndex((item) => item.id === file.id)
/**
 * 选中一行
 * @param checked 是否选中
 * @param file 文件
 * @param isCalcCheckAll 是否计算全选
 */
const handleCheckOne = (checked: boolean, file: File, isCalcCheckAll: boolean) => {
  if (checked) {
    checkedFiles.value.push(file)
    checkedStatus.value[file.id] = true
  } else {
    const index = findCheckedIndex(file)
    if (index > -1) {
      checkedFiles.value.splice(index, 1)
      checkedStatus.value[file.id] = false
      isCheckAll.value = false
    }
  }
  // 计算全选框状态
  const calculateIsCheckAll = () => {
    isCheckAll.value = list.value.every((file) => checkedStatus.value[file.id])
    // 计算中间状态：不是全部选中 && 任意一个选中
    isIndeterminate.value =
      !isCheckAll.value && list.value.some((file) => checkedStatus.value[file.id])
  }
  // 计算全选框状态
  if (isCalcCheckAll) {
    calculateIsCheckAll()
  }
}
/** 使用选中 */
const handleUse = () => {
  if (checkedFiles.value.length === 0) {
    message.warning('请选择文件')
  } else {
    let fileList = [] as EmptyArrayType //选中文件地址数组
    checkedFiles.value.forEach((element) => {
      fileList.push(element)
    })
    emit('selectFile', fileList)
  }
}
</script>

<style lang="scss" scoped>
.list-item-box {
  .active-item {
    border: 1px solid var(--el-color-primary);
  }
}

.waterfall-item {
  border: 1px solid var(--el-border-color);
  margin-bottom: 10px;
}

.material-img {
  width: 100%;
}

p {
  line-height: 30px;
}
</style>
